package middleware

import (
	"github.com/pkg/errors"
	"go-fast/global"
	"net/http/httputil"
	"runtime"

	"github.com/gin-gonic/gin"
)

func Recovery() gin.HandlerFunc {
	var (
		err error
		ok  bool
	)

	return func(c *gin.Context) {
		defer func() {
			if v := recover(); v != nil {
				// 解析panic原因
				if err, ok = v.(error); !ok {
					if s, ok := v.(string); ok {
						err = errors.New(s)
					}
				}

				// 包装错误
				err = errors.Wrap(err, "服务内部错误")
				// 获取堆栈信息
				stackBuf := make([]byte, 4096)
				n := runtime.Stack(stackBuf, false)
				dumpReq, _ := httputil.DumpRequest(c.Request, true)

				// 日志输出
				if global.Log != nil {
					global.Log.Errorf("[Recovery] panic recovered: %s\n%s\n%s", dumpReq, err, stackBuf[:n])
				}
			}
		}()
		c.Next()
	}
}
